import os
import sys
import json
import asyncio
from typing import Any, Dict, List, Optional
from pathlib import Path
from datetime import datetime
from loguru import logger


def ensure_directory(path: str) -> Path:
    """确保目录存在"""
    dir_path = Path(path)
    dir_path.mkdir(parents=True, exist_ok=True)
    return dir_path


def get_timestamp() -> str:
    """获取当前时间戳字符串"""
    return datetime.now().strftime("%Y%m%d_%H%M%S")


def safe_json_load(file_path: str, default: Any = None) -> Any:
    """安全加载JSON文件"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        logger.warning(f"加载JSON文件失败 {file_path}: {e}")
        return default


def safe_json_save(data: Any, file_path: str) -> bool:
    """安全保存JSON文件"""
    try:
        ensure_directory(Path(file_path).parent)
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2, default=str)
        return True
    except Exception as e:
        logger.error(f"保存JSON文件失败 {file_path}: {e}")
        return False


def format_duration(seconds: float) -> str:
    """格式化时长"""
    if seconds < 60:
        return f"{seconds:.1f}秒"
    elif seconds < 3600:
        minutes = int(seconds // 60)
        secs = seconds % 60
        return f"{minutes}分{secs:.1f}秒"
    else:
        hours = int(seconds // 3600)
        minutes = int((seconds % 3600) // 60)
        secs = seconds % 60
        return f"{hours}小时{minutes}分{secs:.1f}秒"


def format_file_size(size_bytes: int) -> str:
    """格式化文件大小"""
    if size_bytes == 0:
        return "0B"
    
    size_names = ["B", "KB", "MB", "GB", "TB"]
    i = 0
    while size_bytes >= 1024 and i < len(size_names) - 1:
        size_bytes /= 1024.0
        i += 1
    
    return f"{size_bytes:.1f}{size_names[i]}"


def validate_url(url: str) -> bool:
    """验证URL格式"""
    import re
    pattern = re.compile(
        r'^https?://'  # http:// or https://
        r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|'  # domain...
        r'localhost|'  # localhost...
        r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...or ip
        r'(?::\d+)?'  # optional port
        r'(?:/?|[/?]\S+)$', re.IGNORECASE)
    return pattern.match(url) is not None


def run_async_in_thread(coro):
    """在新线程中运行异步函数"""
    import threading
    
    def run_in_thread():
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            return loop.run_until_complete(coro)
        finally:
            loop.close()
    
    thread = threading.Thread(target=run_in_thread)
    thread.daemon = True
    thread.start()
    return thread


def get_system_info() -> Dict[str, Any]:
    """获取系统信息"""
    import platform
    import psutil
    
    return {
        "platform": platform.system(),
        "platform_version": platform.version(),
        "architecture": platform.architecture()[0],
        "processor": platform.processor(),
        "python_version": platform.python_version(),
        "memory_total": psutil.virtual_memory().total,
        "memory_available": psutil.virtual_memory().available,
        "disk_total": psutil.disk_usage('/').total,
        "disk_free": psutil.disk_usage('/').free,
        "cpu_count": psutil.cpu_count(),
    }


def generate_selector_alternatives(selector: str) -> List[str]:
    """生成选择器的替代方案"""
    alternatives = [selector]
    
    # 如果是ID选择器，生成属性选择器
    if selector.startswith('#'):
        element_id = selector[1:]
        alternatives.append(f'[id="{element_id}"]')
        alternatives.append(f'*[id="{element_id}"]')
    
    # 如果是类选择器，生成属性选择器
    elif selector.startswith('.'):
        class_name = selector[1:]
        alternatives.append(f'[class*="{class_name}"]')
        alternatives.append(f'*[class*="{class_name}"]')
    
    # 添加更多通用选择器
    if ' ' in selector:  # 后代选择器
        parts = selector.split(' ')
        # 尝试只用最后一部分
        alternatives.append(parts[-1])
        # 尝试用直接子选择器
        alternatives.append(' > '.join(parts))
    
    return list(set(alternatives))  # 去重


def sanitize_filename(filename: str) -> str:
    """清理文件名，移除不安全字符"""
    import re
    
    # 移除或替换不安全字符
    filename = re.sub(r'[<>:"/\\|?*]', '_', filename)
    filename = re.sub(r'\s+', '_', filename)  # 空格替换为下划线
    filename = filename.strip('._')  # 移除开头结尾的点和下划线
    
    # 限制长度
    if len(filename) > 200:
        filename = filename[:200]
    
    return filename or "unnamed"


def deep_merge_dict(dict1: Dict, dict2: Dict) -> Dict:
    """深度合并字典"""
    result = dict1.copy()
    
    for key, value in dict2.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge_dict(result[key], value)
        else:
            result[key] = value
    
    return result


def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str:
    """截断文本"""
    if len(text) <= max_length:
        return text
    return text[:max_length - len(suffix)] + suffix


def retry_on_exception(max_retries: int = 3, delay: float = 1.0, exceptions: tuple = (Exception,)):
    """重试装饰器"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            last_exception = None
            
            for attempt in range(max_retries + 1):
                try:
                    return func(*args, **kwargs)
                except exceptions as e:
                    last_exception = e
                    if attempt < max_retries:
                        logger.warning(f"第{attempt + 1}次尝试失败: {e}, {delay}秒后重试...")
                        import time
                        time.sleep(delay)
                    else:
                        logger.error(f"重试{max_retries}次后仍然失败: {e}")
            
            raise last_exception
        
        return wrapper
    return decorator


class ThreadSafeCounter:
    """线程安全计数器"""
    
    def __init__(self, initial_value: int = 0):
        self._value = initial_value
        self._lock = threading.Lock()
    
    def increment(self) -> int:
        with self._lock:
            self._value += 1
            return self._value
    
    def decrement(self) -> int:
        with self._lock:
            self._value -= 1
            return self._value
    
    @property
    def value(self) -> int:
        with self._lock:
            return self._value


def setup_logging_config(level: str = "INFO", log_file: Optional[str] = None):
    """设置日志配置"""
    import sys
    from loguru import logger
    
    # 移除默认处理器
    logger.remove()
    
    # 添加控制台处理器
    logger.add(
        sys.stdout,
        level=level,
        format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level>",
        colorize=True
    )
    
    # 添加文件处理器（如果指定了日志文件）
    if log_file:
        ensure_directory(Path(log_file).parent)
        logger.add(
            log_file,
            level=level,
            format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} | {message}",
            rotation="10 MB",
            retention="10 days",
            compression="zip"
        )